//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <xllp_lcd.h>
#include <bulverde.h>
#include "display_def.h"
#include <util.h>
#include <udelay.h>

static void LCDClearStatusReg()
{
    // Clear the status registers by writing 1's to each bit.
    LCSR0 = ( LCD_LDD | LCD_SOF0| LCD_BER | LCD_ABC | LCD_IU0   |
                          LCD_IU1 | LCD_OU  | LCD_QD  | LCD_EOF0| LCD_BS0   |
                          LCD_SINT| LCD_RD_ST | LCD_CMD_INTR );

    LCSR1 = ( LCD_SOF1| LCD_SOF2| LCD_SOF3| LCD_SOF4| LCD_SOF5  | LCD_SOF6  |
                          LCD_EOF1| LCD_EOF2| LCD_EOF3| LCD_EOF4| LCD_EOF5  | LCD_EOF6  |
                          LCD_BS1 | LCD_BS2 | LCD_BS3 | LCD_BS4 | LCD_BS5   | LCD_BS6   |
                                    LCD_IU2 | LCD_IU3 | LCD_IU4 | LCD_IU5   | LCD_IU6 );
}

void LcdCtrl_Init_Sub(int, int, int);
void LcdCtrl_Init(DisplayContext *pCxt)
{
    int PCD = 0;
    unsigned int val_CCCR_L = 0;

    int LCLK = 0;

    int val_BPP;

    int PixelDataFormat;

    if (pCxt->basePlaneFormat == COLOR_RGB565) {
        PixelDataFormat = PDFOR_00;
    }
    else {
        PixelDataFormat = PDFOR_11; // RGBT555
    }

    LCCR0 = 0;
    LCCR1 = 0;
    LCCR2 = 0;
    LCCR3 = 0;
    LCCR4 = 0;
    LCCR5 = (LCD_SOFM1|LCD_SOFM2|LCD_SOFM3|LCD_SOFM4|LCD_SOFM5|LCD_SOFM6|
                        LCD_EOFM1|LCD_EOFM2|LCD_EOFM3|LCD_EOFM4|LCD_EOFM5|LCD_EOFM6|
                        LCD_BSM1 |LCD_BSM2 |LCD_BSM3 |LCD_BSM4 |LCD_BSM5 |LCD_BSM6 |
                        LCD_IUM1 |LCD_IUM2 |LCD_IUM3 |LCD_IUM4 |LCD_IUM5 |LCD_IUM6 );

    // Determine the frame buffer size for the DMA transfer length.
    // Scale the size based on the bpp of the frame buffer to determine
    // an actual size in bytes
    int FrameBufferSize = LCD_WIDTH * LCD_HEIGHT;
    FrameBufferSize <<= 1; // 16BPP

    // Enable the LCD
    CKEN = (CKEN & XLLP_CLKEN_MASK) | CLK_LCD ;
//
    LCD_FRAME_DESCRIPTOR *frameDescriptorCh0fd1 = (LCD_FRAME_DESCRIPTOR *)pCxt->vaChan0Desc;

    // Configure the general purpose frame descriptors
    // Set the physical address of the frame descriptor
    frameDescriptorCh0fd1->FDADR = LCD_FDADR(pCxt->paChan0Desc);

    // Set the physical address of the frame buffer
    frameDescriptorCh0fd1->FSADR = LCD_FSADR(pCxt->paBasePlane);

    // Clear the frame ID
    frameDescriptorCh0fd1->FIDR  = LCD_FIDR(0);

    // Set the DMA transfer length to the size of the frame buffer
    frameDescriptorCh0fd1->LDCMD = LCD_Len(FrameBufferSize);

    // Store the physical address of this frame descriptor in the frame descriptor
    frameDescriptorCh0fd1->PHYSADDR = frameDescriptorCh0fd1->FDADR;

    // FBR0 is cleared and is not used.
    FBR0 = 0;

    // Load the contents of FDADR0 with the physical address of this frame descriptor
    FDADR0 = LCD_FDADR(frameDescriptorCh0fd1->FDADR);

    // Determine the LCLK frequency programmed into the CCCR.
    // This value will be used to calculate a Pixel Clock Divisor (PCD)
    // for a given display type.
    val_CCCR_L = (CCCR & 0x0000001F);

    if (val_CCCR_L < 8) // L = [2 - 7]
        LCLK = (13 * val_CCCR_L) * 100;
    else if (val_CCCR_L < 17) // L = [8 - 16]
        LCLK = ((13 * val_CCCR_L) * 100) >> 1; // THIS
    else if (val_CCCR_L < 32) // L = [17 - 31]
        LCLK = ((13 * val_CCCR_L) * 100) >> 2;

    // Convert the bpp setting into a value that the LCD controller understands.
    val_BPP = O_BPP_16;
    PCD = 8;

    // Configure the LCD Controller Control Registers
    LCCR0 = (LCD_LDM | LCD_SFM | LCD_IUM | LCD_EFM |
            LCD_PAS | LCD_QDM | LCD_BM  | LCD_OUM |
            LCD_RDSTM | LCD_CMDIM | LCD_LDDALT /*| LCD_OUC*/);

    //Init PCD,LCCR1,LCCR2,LCCR3
    LcdCtrl_Init_Sub(val_BPP, PCD, PixelDataFormat);

    LCCR4 = LCD_PAL_FOR(2);
    LCCR4 |= LCD_K1(6) | LCD_K2(6) | LCD_K3(6);

    // Clear LCD Controller status register
    LCDClearStatusReg();
}

void LcdCtrl_Enable(DisplayContext *pCxt)
{
    LCCR0 |= LCD_ENB;
}

void LcdCtrl_Disable(DisplayContext *pCxt)
{
    LCCR0 &= ~LCD_ENB;
}
